home *** CD-ROM | disk | FTP | other *** search
/ Isometric Game Programming with DirectX 7.0 / Isometric Game Programming.iso / source / chapter13 / isohex13_4 / isohex13_4.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-07-19  |  16.3 KB  |  671 lines

  1. /*****************************************************************************
  2. IsoHex13_4.cpp
  3. Ernest S. Pazera
  4. 19JUL2000
  5. Start a WIN32 Application Workspace, add in this file
  6. Requires ddraw.lib and dxguid.lib
  7. Needs DDFuncs.h/cpp, GDICanvas.h/cpp, and TileSet.h/cpp
  8. *****************************************************************************/
  9.  
  10. //////////////////////////////////////////////////////////////////////////////
  11. //INCLUDES
  12. //////////////////////////////////////////////////////////////////////////////
  13. #define WIN32_LEAN_AND_MEAN  
  14.  
  15. #include <windows.h>   
  16. #include "TileSet.h"
  17.  
  18. //////////////////////////////////////////////////////////////////////////////
  19. //DEFINES
  20. //////////////////////////////////////////////////////////////////////////////
  21. //name for our window class
  22. #define WINDOWCLASS "ISOHEX13"
  23. //title of the application
  24. #define WINDOWTITLE "IsoHex 13-4"
  25.  
  26. //map dimensions
  27. const int MAPWIDTH=20;
  28. const int MAPHEIGHT=40;
  29.  
  30. enum IsoDirection{
  31. ISO_NORTH=0,
  32. ISO_NORTHEAST=1,
  33. ISO_EAST=2,
  34. ISO_SOUTHEAST=3,
  35. ISO_SOUTH=4,
  36. ISO_SOUTHWEST=5,
  37. ISO_WEST=6,
  38. ISO_NORTHWEST=7
  39. };
  40.  
  41. //mousemap directions
  42. enum MouseMapDirection{
  43.     MM_CENTER=0,
  44.     MM_NW=1,
  45.     MM_NE=2,
  46.     MM_SW=3,
  47.     MM_SE=4
  48. };
  49.  
  50. //mousemap structure
  51. struct CMouseMap
  52. {
  53.     POINT ptSize;
  54.     POINT ptRef;
  55.     MouseMapDirection* mmdLookUp;
  56. };
  57.  
  58. //////////////////////////////////////////////////////////////////////////////
  59. //PROTOTYPES
  60. //////////////////////////////////////////////////////////////////////////////
  61. bool Prog_Init();//game data initalizer
  62. void Prog_Loop();//main game loop
  63. void Prog_Done();//game clean up
  64. POINT StagMap_TilePlotter(POINT ptMap,int iTileWidth,int iTileHeight);
  65. POINT StagMap_TileWalker(POINT ptStart,IsoDirection Dir);
  66. POINT StagMap_MouseMapper(POINT ptMouse,CMouseMap* pmm);
  67. void SetUpSpaces();//sets up spaces
  68. void SetUpMap();
  69. void DrawMap();
  70. void ShowIsoCursor();
  71. void LoadMouseMap(CMouseMap* pmm,LPCTSTR lpszFileName);
  72. void ClipScreenAnchor();
  73.  
  74. //////////////////////////////////////////////////////////////////////////////
  75. //GLOBALS
  76. //////////////////////////////////////////////////////////////////////////////
  77. HINSTANCE hInstMain=NULL;//main application handle
  78. HWND hWndMain=NULL;//handle to our main window
  79. LPDIRECTDRAW7 lpdd=NULL;//directdraw
  80. LPDIRECTDRAWSURFACE7 lpddsMain=NULL;//primary surface
  81. LPDIRECTDRAWSURFACE7 lpddsBack=NULL;//back buffer
  82. LPDIRECTDRAWCLIPPER lpddClipper=NULL;//clipper
  83. CTileSet tsIso;//tileset
  84. CTileSet tsCursor;//cursor
  85. int iTileMap[MAPWIDTH][MAPHEIGHT];
  86. POINT ptCursor;//cursor position
  87.  
  88. //spaces
  89. RECT rcWorldSpace;//worldspace
  90. RECT rcScreenSpace;//screen space(also, view space)
  91. RECT rcAnchorSpace;//anchor space
  92. POINT ptScreenAnchor;//screen anchor
  93. POINT ptScreenAnchorScroll;//scrolling for the screen anchor
  94.  
  95. //mouse map
  96. CMouseMap mmMouseMap;
  97.  
  98.  
  99. //////////////////////////////////////////////////////////////////////////////
  100. //WINDOWPROC
  101. //////////////////////////////////////////////////////////////////////////////
  102. LRESULT CALLBACK TheWindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
  103. {
  104.     //which message did we get?
  105.     switch(uMsg)
  106.     {
  107.     case WM_MOUSEMOVE:
  108.         {
  109.             //grab mouse coordinate
  110.             POINT ptMouse;
  111.             ptMouse.x=LOWORD(lParam);
  112.             ptMouse.y=HIWORD(lParam);
  113.             //mousemap the mouse coordinates
  114.             ptCursor=StagMap_MouseMapper(ptMouse,&mmMouseMap);
  115.  
  116.             //clip cursor to tilemap
  117.             if(ptCursor.x<0) ptCursor.x=0;
  118.             if(ptCursor.y<0) ptCursor.y=0;
  119.             if(ptCursor.x>MAPWIDTH-1) ptCursor.x=MAPWIDTH-1;
  120.             if(ptCursor.y>MAPHEIGHT-1) ptCursor.y=MAPHEIGHT-1;
  121.  
  122.             //check for scrolling zones
  123.             ptScreenAnchorScroll.x=0;
  124.             ptScreenAnchorScroll.y=0;
  125.             //top
  126.             if(ptMouse.y<8)
  127.             {
  128.                 ptScreenAnchorScroll.y=-(8-ptMouse.y);
  129.             }
  130.             //bottom
  131.             if(ptMouse.y>472)
  132.             {
  133.                 ptScreenAnchorScroll.y=(ptMouse.y-472);
  134.             }
  135.             //left
  136.             if(ptMouse.x<8)
  137.             {
  138.                 ptScreenAnchorScroll.x=-(8-ptMouse.x);
  139.             }
  140.             //right
  141.             if(ptMouse.x>632)
  142.             {
  143.                 ptScreenAnchorScroll.x=(ptMouse.x-632);
  144.             }
  145.  
  146.             return(0);
  147.         }break;
  148.     case WM_KEYDOWN:
  149.         {
  150.             //if escape hit, destroy window
  151.             if(wParam==VK_ESCAPE) DestroyWindow(hWndMain);
  152.             //handled, so return 0
  153.             return(0);
  154.         }break;
  155.     case WM_DESTROY://the window is being destroyed
  156.         {
  157.  
  158.             //tell the application we are quitting
  159.             PostQuitMessage(0);
  160.  
  161.             //handled message, so return 0
  162.             return(0);
  163.  
  164.         }break;
  165.     case WM_PAINT://the window needs repainting
  166.         {
  167.             //a variable needed for painting information
  168.             PAINTSTRUCT ps;
  169.             
  170.             //start painting
  171.             HDC hdc=BeginPaint(hwnd,&ps);
  172.  
  173.             /////////////////////////////
  174.             //painting code would go here
  175.             /////////////////////////////
  176.  
  177.             //end painting
  178.             EndPaint(hwnd,&ps);
  179.                         
  180.             //handled message, so return 0
  181.             return(0);
  182.         }break;
  183.     }
  184.  
  185.     //pass along any other message to default message handler
  186.     return(DefWindowProc(hwnd,uMsg,wParam,lParam));
  187. }
  188.  
  189.  
  190. //////////////////////////////////////////////////////////////////////////////
  191. //WINMAIN
  192. //////////////////////////////////////////////////////////////////////////////
  193. int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd)
  194. {
  195.     //assign instance to global variable
  196.     hInstMain=hInstance;
  197.  
  198.     //create window class
  199.     WNDCLASSEX wcx;
  200.  
  201.     //set the size of the structure
  202.     wcx.cbSize=sizeof(WNDCLASSEX);
  203.  
  204.     //class style
  205.     wcx.style=CS_OWNDC | CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
  206.  
  207.     //window procedure
  208.     wcx.lpfnWndProc=TheWindowProc;
  209.  
  210.     //class extra
  211.     wcx.cbClsExtra=0;
  212.  
  213.     //window extra
  214.     wcx.cbWndExtra=0;
  215.  
  216.     //application handle
  217.     wcx.hInstance=hInstMain;
  218.  
  219.     //icon
  220.     wcx.hIcon=LoadIcon(NULL,IDI_APPLICATION);
  221.  
  222.     //cursor
  223.     wcx.hCursor=LoadCursor(NULL,IDC_ARROW);
  224.  
  225.     //background color
  226.     wcx.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH);
  227.  
  228.     //menu
  229.     wcx.lpszMenuName=NULL;
  230.  
  231.     //class name
  232.     wcx.lpszClassName=WINDOWCLASS;
  233.  
  234.     //small icon
  235.     wcx.hIconSm=NULL;
  236.  
  237.     //register the window class, return 0 if not successful
  238.     if(!RegisterClassEx(&wcx)) return(0);
  239.  
  240.     //create main window
  241.     hWndMain=CreateWindowEx(0,WINDOWCLASS,WINDOWTITLE, WS_POPUP | WS_VISIBLE,0,0,320,240,NULL,NULL,hInstMain,NULL);
  242.  
  243.     //error check
  244.     if(!hWndMain) return(0);
  245.  
  246.     //if program initialization failed, then return with 0
  247.     if(!Prog_Init()) return(0);
  248.  
  249.     //message structure
  250.     MSG msg;
  251.  
  252.     //message pump
  253.     for(;;)    
  254.     {
  255.         //look for a message
  256.         if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
  257.         {
  258.             //there is a message
  259.  
  260.             //check that we arent quitting
  261.             if(msg.message==WM_QUIT) break;
  262.             
  263.             //translate message
  264.             TranslateMessage(&msg);
  265.  
  266.             //dispatch message
  267.             DispatchMessage(&msg);
  268.         }
  269.  
  270.         //run main game loop
  271.         Prog_Loop();
  272.     }
  273.     
  274.     //clean up program data
  275.     Prog_Done();
  276.  
  277.     //return the wparam from the WM_QUIT message
  278.     return(msg.wParam);
  279. }
  280.  
  281. //////////////////////////////////////////////////////////////////////////////
  282. //INITIALIZATION
  283. //////////////////////////////////////////////////////////////////////////////
  284. bool Prog_Init()
  285. {
  286.     //set up ddraw
  287.     lpdd=LPDD_Create(hWndMain,DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT);
  288.     lpdd->SetDisplayMode(640,480,16,0,0);
  289.  
  290.     //set up primary surface
  291.     lpddsMain=LPDDS_CreatePrimary(lpdd,1);
  292.  
  293.     //set up back buffer
  294.     lpddsBack=LPDDS_GetSecondary(lpddsMain);
  295.  
  296.     //create clipper
  297.     lpdd->CreateClipper(0,&lpddClipper,NULL);
  298.     lpddClipper->SetHWnd(0,hWndMain);
  299.     lpddsBack->SetClipper(lpddClipper);
  300.  
  301.     //load in tileset
  302.     tsIso.Load(lpdd,"IsoHex13_4-1.bmp");
  303.     tsCursor.Load(lpdd,"IsoHex13_4-2.bmp");
  304.     //load in mousemap
  305.     LoadMouseMap(&mmMouseMap,"IsoHex13_4-3.bmp");
  306.     //set up mousemap reference point
  307.     POINT ptMap;
  308.     ptMap.x=0;
  309.     ptMap.y=0;
  310.     mmMouseMap.ptRef=StagMap_TilePlotter(ptMap,mmMouseMap.ptSize.x,mmMouseMap.ptSize.y);
  311.     mmMouseMap.ptRef.x+=tsIso.GetTileList()[0].rcDstExt.left;
  312.     mmMouseMap.ptRef.y+=tsIso.GetTileList()[0].rcDstExt.top;
  313.  
  314.     //set up spaces
  315.     SetUpSpaces();
  316.  
  317.     //set up the tilemap
  318.     SetUpMap();
  319.  
  320.     return(true);//return success
  321. }
  322.  
  323. //////////////////////////////////////////////////////////////////////////////
  324. //CLEANUP
  325. //////////////////////////////////////////////////////////////////////////////
  326. void Prog_Done()
  327. {
  328.     //deallocate lookup table for mousemap
  329.     delete [] mmMouseMap.mmdLookUp;
  330.     //clean up clipper
  331.     LPDDCLIP_Release(&lpddClipper);
  332.     //clean up primary surface
  333.     LPDDS_Release(&lpddsMain);
  334.     //clean up ddraw
  335.     LPDD_Release(&lpdd);
  336. }
  337.  
  338. //////////////////////////////////////////////////////////////////////////////
  339. //MAIN GAME LOOP
  340. //////////////////////////////////////////////////////////////////////////////
  341. void Prog_Loop()
  342. {
  343.     //clear out back buffer
  344.     DDBLTFX ddbltfx;
  345.     DDBLTFX_ColorFill(&ddbltfx,0);
  346.     lpddsBack->Blt(NULL,NULL,NULL,DDBLT_WAIT | DDBLT_COLORFILL,&ddbltfx);
  347.  
  348.     //scroll the map
  349.     ptScreenAnchor.x+=ptScreenAnchorScroll.x;
  350.     ptScreenAnchor.y+=ptScreenAnchorScroll.y;
  351.     ClipScreenAnchor();
  352.  
  353.     //show the board
  354.     DrawMap();
  355.  
  356.     //show the cursor
  357.     ShowIsoCursor();
  358.  
  359.     //flip
  360.     lpddsMain->Flip(NULL,DDFLIP_WAIT);
  361. }
  362.  
  363. POINT StagMap_TilePlotter(POINT ptMap,int iTileWidth,int iTileHeight)
  364. {
  365.     POINT ptReturn;
  366.     //calculate pixel position for the map position given
  367.     ptReturn.x=ptMap.x*iTileWidth+(ptMap.y & 1)*iTileWidth/2;
  368.     ptReturn.y=ptMap.y*iTileHeight/2;
  369.     //return calculate point
  370.     return(ptReturn);
  371. }
  372.  
  373. void SetUpMap()
  374. {
  375.     //randomly set up the map
  376.     for(int x=0;x<MAPWIDTH;x++)
  377.     {
  378.         for(int y=0;y<MAPHEIGHT;y++)
  379.         {
  380.             iTileMap[x][y]=rand()%(tsIso.GetTileCount());
  381.         }
  382.     }
  383. }
  384.  
  385. void DrawMap()
  386. {
  387.     POINT ptTile;//tile pixel coordinate
  388.     POINT ptMap;//map coordinate
  389.     //the y loop is outside, because we must blit in horizontal rows
  390.     for(int y=0;y<MAPHEIGHT;y++)
  391.     {
  392.         for(int x=0;x<MAPWIDTH;x++)
  393.         {
  394.             //get pixel coordinate for map position
  395.             ptMap.x=x;
  396.             ptMap.y=y;
  397.             ptTile=StagMap_TilePlotter(ptMap,mmMouseMap.ptSize.x,mmMouseMap.ptSize.y);
  398.             //plot the tile(adjust for anchor)
  399.             tsIso.PutTile(lpddsBack,ptTile.x-ptScreenAnchor.x,ptTile.y-ptScreenAnchor.y,iTileMap[x][y]);
  400.         }
  401.     }
  402. }
  403.  
  404. void SetUpSpaces()
  405. {
  406.     //set up screen space
  407.     SetRect(&rcScreenSpace,0,0,640,480);
  408.     
  409.     //grab tile rectangle from tileset
  410.     RECT rcTile1;
  411.     RECT rcTile2;
  412.     POINT ptPlot;
  413.     POINT ptMap;
  414.  
  415.     //grab tiles from extents
  416.     CopyRect(&rcTile1,&tsIso.GetTileList()[0].rcDstExt);
  417.     CopyRect(&rcTile2,&tsIso.GetTileList()[0].rcDstExt);
  418.  
  419.     //move first tile to upper left position
  420.     ptMap.x=0;
  421.     ptMap.y=0;
  422.     ptPlot=StagMap_TilePlotter(ptMap,mmMouseMap.ptSize.x,mmMouseMap.ptSize.y);
  423.     OffsetRect(&rcTile1,ptPlot.x,ptPlot.y);
  424.  
  425.     //move first tile to lower right position
  426.     ptMap.x=MAPWIDTH-1;
  427.     ptMap.y=MAPHEIGHT-1;
  428.     ptPlot=StagMap_TilePlotter(ptMap,mmMouseMap.ptSize.x,mmMouseMap.ptSize.y);
  429.     OffsetRect(&rcTile2,ptPlot.x,ptPlot.y);
  430.  
  431.     //combine these two tiles into world space
  432.     UnionRect(&rcWorldSpace,&rcTile1,&rcTile2);
  433.  
  434.     //copy worldspace to anchor space
  435.     CopyRect(&rcAnchorSpace,&rcWorldSpace);
  436.  
  437.     //subtract out screenspace
  438.     //adjust right edge
  439.     rcAnchorSpace.right-=(rcScreenSpace.right-rcScreenSpace.left);
  440.     //make sure right not less than left
  441.     if(rcAnchorSpace.right<rcAnchorSpace.left) rcAnchorSpace.right=rcAnchorSpace.left;
  442.     //adjust bottom edge
  443.     rcAnchorSpace.bottom-=(rcScreenSpace.bottom-rcScreenSpace.top);
  444.     //make sure bottom not less than top
  445.     if(rcAnchorSpace.bottom<rcAnchorSpace.top) rcAnchorSpace.bottom=rcAnchorSpace.top;
  446.  
  447.     //adjust edges of anchorspace for "no jaggies"
  448.     //add 1/2 height to top
  449.     rcAnchorSpace.top+=(mmMouseMap.ptSize.y/2);
  450.     //subtract 1/2 height from bottom
  451.     rcAnchorSpace.bottom-=(mmMouseMap.ptSize.y/2);
  452.     //add 1/2 width to left
  453.     rcAnchorSpace.left+=(mmMouseMap.ptSize.x/2);
  454.     //subtract 1/2 width from right
  455.     rcAnchorSpace.right-=(mmMouseMap.ptSize.x/2);
  456.  
  457.     //initialize screen anchor
  458.     ptScreenAnchor.x=rcAnchorSpace.left;
  459.     ptScreenAnchor.y=rcAnchorSpace.top;
  460.  
  461.     //initialize cursor
  462.     ptCursor.x=0;
  463.     ptCursor.y=0;
  464. }
  465.  
  466. POINT StagMap_TileWalker(POINT ptStart, IsoDirection Dir)
  467. {
  468.     //depending on direction, move the point
  469.     switch(Dir)
  470.     {
  471.     case ISO_NORTH:
  472.         {
  473.             ptStart.y-=2;
  474.         }break;
  475.     case ISO_NORTHEAST:
  476.         {
  477.             ptStart.x+=(ptStart.y&1);
  478.             ptStart.y--;
  479.         }break;
  480.     case ISO_EAST:
  481.         {
  482.             ptStart.x++;
  483.         }break;
  484.     case ISO_SOUTHEAST:
  485.         {
  486.             ptStart.x+=(ptStart.y&1);
  487.             ptStart.y++;
  488.         }break;
  489.     case ISO_SOUTH:
  490.         {
  491.             ptStart.y+=2;
  492.         }break;
  493.     case ISO_SOUTHWEST:
  494.         {
  495.             ptStart.x+=((ptStart.y&1)-1);
  496.             ptStart.y++;
  497.         }break;
  498.     case ISO_WEST:
  499.         {
  500.             ptStart.x--;
  501.         }break;
  502.     case ISO_NORTHWEST:
  503.         {
  504.             ptStart.x+=((ptStart.y&1)-1);
  505.             ptStart.y--;
  506.         }break;
  507.     }
  508.     //return the point
  509.     return(ptStart);
  510. }
  511.  
  512. void ShowIsoCursor()
  513. {
  514.     //copy cursor position
  515.     POINT ptMap=ptCursor;
  516.  
  517.     //plot cursor position
  518.     POINT ptPlot=StagMap_TilePlotter(ptMap,mmMouseMap.ptSize.x,mmMouseMap.ptSize.y);
  519.     
  520.     //put the cursor image
  521.     tsCursor.PutTile(lpddsBack,ptPlot.x-ptScreenAnchor.x,ptPlot.y-ptScreenAnchor.y,0);
  522. }
  523.  
  524. void LoadMouseMap(CMouseMap* pmm,LPCTSTR lpszfilename)
  525. {
  526.     //create canvas
  527.     CGDICanvas gdic;
  528.     //load file
  529.     gdic.Load(NULL,lpszfilename);
  530.     //assign width/height
  531.     pmm->ptSize.x=gdic.GetWidth();
  532.     pmm->ptSize.y=gdic.GetHeight();
  533.     //allocate space for the lookup table
  534.     pmm->mmdLookUp= new
  535.         MouseMapDirection[gdic.GetWidth()*gdic.GetHeight()];
  536.     //colorref values for filling lookup
  537.     COLORREF crNW=GetPixel(gdic,0,0);
  538.     COLORREF crNE=GetPixel(gdic,gdic.GetWidth()-1,0);
  539.     COLORREF crSW=GetPixel(gdic,0,gdic.GetHeight()-1);
  540.     COLORREF crSE=GetPixel(gdic,gdic.GetWidth()-1, gdic.GetHeight()-1);
  541.     //test pixel color
  542.     COLORREF crTest;
  543.     //scan convert bitmap into lookup values
  544.     for(int y=0;y<gdic.GetHeight();y++)
  545.     {
  546.         for(int x=0;x<gdic.GetWidth();x++)
  547.         {
  548.             //grab test pixel
  549.             crTest=GetPixel(gdic,x,y);
  550.             //set lookup to default
  551.             pmm->mmdLookUp[x+y*pmm->ptSize.x]=MM_CENTER;
  552.             //check colors
  553.             if(crTest==crNW)
  554.                 pmm->mmdLookUp[x+y*pmm->ptSize.x]=MM_NW;
  555.             if(crTest==crNE)
  556.                 pmm->mmdLookUp[x+y*pmm->ptSize.x]=MM_NE;
  557.             if(crTest==crSW)
  558.                 pmm->mmdLookUp[x+y*pmm->ptSize.x]=MM_SW;
  559.             if(crTest==crSE)
  560.                 pmm->mmdLookUp[x+y*pmm->ptSize.x]=MM_SE;
  561.         }
  562.     }
  563. }
  564.  
  565. void ClipScreenAnchor()
  566. {
  567.     //clip to left
  568.     if(ptScreenAnchor.x<rcAnchorSpace.left) ptScreenAnchor.x=rcAnchorSpace.left;
  569.     //clip to top
  570.     if(ptScreenAnchor.y<rcAnchorSpace.top) ptScreenAnchor.y=rcAnchorSpace.top;
  571.     //clip to right
  572.     if(ptScreenAnchor.x>=rcAnchorSpace.right) ptScreenAnchor.x=rcAnchorSpace.right-1;
  573.     //clip to bottom
  574.     if(ptScreenAnchor.y>=rcAnchorSpace.bottom) ptScreenAnchor.y=rcAnchorSpace.bottom-1;
  575. }
  576.  
  577. POINT StagMap_MouseMapper(POINT ptMouse,CMouseMap* pmm)
  578. {
  579.     //step1:screen to world
  580.     ptMouse.x+=ptScreenAnchor.x;
  581.     ptMouse.y+=ptScreenAnchor.y;
  582.  
  583.     //step2:relative world coordinates
  584.     ptMouse.x-=pmm->ptRef.x;
  585.     ptMouse.y-=pmm->ptRef.y;
  586.  
  587.     //step3:mousemap coords
  588.     POINT ptMouseMapCoarse;
  589.     POINT ptMouseMapFine;
  590.     //coarse mousemap coords
  591.     ptMouseMapCoarse.x=ptMouse.x/pmm->ptSize.x;
  592.     ptMouseMapCoarse.y=ptMouse.y/pmm->ptSize.y;
  593.     //fine mousemap coords
  594.     ptMouseMapFine.x=ptMouse.x%pmm->ptSize.x;
  595.     ptMouseMapFine.y=ptMouse.y%pmm->ptSize.y;
  596.     //adjust for negative fine coordinates
  597.     if(ptMouseMapFine.x<0)
  598.     {
  599.         ptMouseMapFine.x+=pmm->ptSize.x;
  600.         ptMouseMapCoarse.x--;
  601.     }
  602.     if(ptMouseMapFine.y<0)
  603.     {
  604.         ptMouseMapFine.y+=pmm->ptSize.y;
  605.         ptMouseMapCoarse.y--;
  606.     }
  607.  
  608.     //step4:coarse tilewalk
  609.     POINT ptMap;
  610.     ptMap.x=0;
  611.     ptMap.y=0;
  612.     //move north
  613.     while(ptMouseMapCoarse.y<0)
  614.     {
  615.         ptMouseMapCoarse.y++;
  616.         ptMap=StagMap_TileWalker(ptMap,ISO_NORTH);
  617.     }
  618.     //move south
  619.     while(ptMouseMapCoarse.y>0)
  620.     {
  621.         ptMouseMapCoarse.y--;
  622.         ptMap=StagMap_TileWalker(ptMap,ISO_SOUTH);
  623.     }
  624.     //move east
  625.     while(ptMouseMapCoarse.x>0)
  626.     {
  627.         ptMouseMapCoarse.x--;
  628.         ptMap=StagMap_TileWalker(ptMap,ISO_EAST);
  629.     }
  630.     //move west
  631.     while(ptMouseMapCoarse.x<0)
  632.     {
  633.         ptMouseMapCoarse.x++;
  634.         ptMap=StagMap_TileWalker(ptMap,ISO_WEST);
  635.     }
  636.  
  637.     //step5:fine tilewalk
  638.     //get lookup value
  639.     MouseMapDirection mmd=pmm->mmdLookUp[ptMouseMapFine.x+ptMouseMapFine.y*pmm->ptSize.x];
  640.     switch(mmd)
  641.     {
  642.     case MM_CENTER:
  643.         {
  644.             //do nothing
  645.         }break;
  646.     case MM_NW:
  647.         {
  648.             //move northwest
  649.             ptMap=StagMap_TileWalker(ptMap,ISO_NORTHWEST);
  650.         }break;
  651.     case MM_NE:
  652.         {
  653.             //move northeast
  654.             ptMap=StagMap_TileWalker(ptMap,ISO_NORTHEAST);
  655.         }break;
  656.     case MM_SW:
  657.         {
  658.             //move southwest
  659.             ptMap=StagMap_TileWalker(ptMap,ISO_SOUTHWEST);
  660.         }break;
  661.     case MM_SE:
  662.         {
  663.             //move southeast
  664.             ptMap=StagMap_TileWalker(ptMap,ISO_SOUTHEAST);
  665.         }break;
  666.     }
  667.  
  668.     //return map coordinate
  669.     return(ptMap);
  670. }
  671.